
/******************************************************************************
 * Author:  huiaove
 * Email:   huiaove@126.com
 * Date:    2023 6.8
 * Address: TianJin
 * Version: V1.0.0
 * 修改记录：
 *             2023 6.8    张亚辉    初始版本，移植来自Semtech 官方驱动例程，保留部分官方注释         版本号:V1.0.0
 * 功能说明：Sx126x 驱动程序
 * ***************************************************************************/
#include <math.h>
#include "radio.h"
#include "sx126x.h"
#include "LoRa_model.h"
/*!
 * Defines the time required for the TCXO to wakeup [ms].
 */
// 定义 TOCO 唤醒所需的时间
#define BOARD_TCXO_WAKEUP_TIME 0

// 返回当前无线状态   Radio status :RF_IDLE, RF_RX_RUNNING, RF_TX_RYNNING
RadioState_t RadioGetStatus(lora_t *lora);

/*!
 * \brief Configures the radio with the given modem
 *
 * \param [IN] modem Modem to be used [0: FSK, 1: LoRa]
 */
// 设置调制模式 0：FSk 1：Lora
void RadioSetModem(lora_t *lora, RadioModems_t modem);

/*!
 * \brief Sets the channel frequency
 *
 * \param [IN] freq         Channel RF frequency
 */
// 设置通道频率
void RadioSetChannel(lora_t *lora, uint32_t freq);

/*!
 * \brief Checks if the channel is free for the given time
 *
 * \remark The FSK modem is always used for this task as we can select the Rx bandwidth at will.
 *
 * \param [IN] freq                Channel RF frequency in Hertz
 * \param [IN] rxBandwidth         Rx bandwidth in Hertz
 * \param [IN] rssiThresh          RSSI threshold in dBm
 * \param [IN] maxCarrierSenseTime Max time in milliseconds while the RSSI is measured
 *
 * \retval isFree         [true: Channel is free, false: Channel is not free]
 */
// 检测通道是否在指定的时间内空闲
bool RadioIsChannelFree(lora_t *lora, uint32_t freq, uint32_t rxBandwidth, int16_t rssiThresh, uint32_t maxCarrierSenseTime);

/*!
 * \brief Generates a 32 bits random value based on the RSSI readings
 *
 * \remark This function sets the radio in LoRa modem mode and disables
 *         all interrupts.
 *         After calling this function either Radio.SetRxConfig or
 *         Radio.SetTxConfig functions must be called.
 *
 * \retval randomValue    32 bits random value
 */
// 根据RSSI 值生成32位随机数
uint32_t RadioRandom(lora_t *lora);

/*!
 * \brief Sets the reception parameters
 *
 * \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]
 * \param [IN] bandwidth    Sets the bandwidth
 *                          FSK : >= 2600 and <= 250000 Hz
 *                          LoRa: [0: 125 kHz, 1: 250 kHz,
 *                                 2: 500 kHz, 3: Reserved]
 * \param [IN] datarate     Sets the Datarate
 *                          FSK : 600..300000 bits/s
 *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
 *                                10: 1024, 11: 2048, 12: 4096  chips]
 * \param [IN] coderate     Sets the coding rate (LoRa only)
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
 * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)
 *                          FSK : >= 2600 and <= 250000 Hz
 *                          LoRa: N/A ( set to 0 )
 * \param [IN] preambleLen  Sets the Preamble length
 *                          FSK : Number of bytes
 *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
 * \param [IN] symbTimeout  Sets the RxSingle timeout value
 *                          FSK : timeout in number of bytes
 *                          LoRa: timeout in symbols
 * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
 * \param [IN] payloadLen   Sets payload length when fixed length is used
 * \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]
 * \param [IN] FreqHopOn    Enables disables the intra-packet frequency hopping
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [0: OFF, 1: ON]
 * \param [IN] HopPeriod    Number of symbols between each hop
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: Number of symbols
 * \param [IN] iqInverted   Inverts IQ signals (LoRa only)
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [0: not inverted, 1: inverted]
 * \param [IN] rxContinuous Sets the reception in continuous mode
 *                          [false: single mode, true: continuous mode]
 */
// 设置接收参数
void RadioSetRxConfig(lora_t *lora, RadioModems_t modem, uint32_t bandwidth,
                      uint32_t datarate, uint8_t coderate,
                      uint32_t bandwidthAfc, uint16_t preambleLen,
                      uint16_t symbTimeout, bool fixLen,
                      uint8_t payloadLen,
                      bool crcOn, bool FreqHopOn, uint8_t HopPeriod,
                      bool iqInverted, bool rxContinuous);

/*!
 * \brief Sets the transmission parameters
 *
 * \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]
 * \param [IN] power        Sets the output power [dBm]
 * \param [IN] fdev         Sets the frequency deviation (FSK only)
 *                          FSK : [Hz]
 *                          LoRa: 0
 * \param [IN] bandwidth    Sets the bandwidth (LoRa only)
 *                          FSK : 0
 *                          LoRa: [0: 125 kHz, 1: 250 kHz,
 *                                 2: 500 kHz, 3: Reserved]
 * \param [IN] datarate     Sets the Datarate
 *                          FSK : 600..300000 bits/s
 *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
 *                                10: 1024, 11: 2048, 12: 4096  chips]
 * \param [IN] coderate     Sets the coding rate (LoRa only)
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
 * \param [IN] preambleLen  Sets the preamble length
 *                          FSK : Number of bytes
 *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
 * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
 * \param [IN] crcOn        Enables disables the CRC [0: OFF, 1: ON]
 * \param [IN] FreqHopOn    Enables disables the intra-packet frequency hopping
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [0: OFF, 1: ON]
 * \param [IN] HopPeriod    Number of symbols between each hop
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: Number of symbols
 * \param [IN] iqInverted   Inverts IQ signals (LoRa only)
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [0: not inverted, 1: inverted]
 * \param [IN] timeout      Transmission timeout [ms]
 */
// 设置发送参数
void RadioSetTxConfig(lora_t *lora, RadioModems_t modem, int8_t power, uint32_t fdev,
                      uint32_t bandwidth, uint32_t datarate,
                      uint8_t coderate, uint16_t preambleLen,
                      bool fixLen, bool crcOn, bool FreqHopOn,
                      uint8_t HopPeriod, bool iqInverted);

/*!
 * \brief Checks if the given RF frequency is supported by the hardware
 *
 * \param [IN] frequency RF frequency to be checked
 * \retval isSupported [true: supported, false: unsupported]
 */
// 检测硬件是否支持给定的频率
bool RadioCheckRfFrequency(lora_t *lora, uint32_t frequency);

/*!
 * \brief Computes the packet time on air in ms for the given payload
 *
 * \Remark Can only be called once SetRxConfig or SetTxConfig have been called
 *
 * \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]
 * \param [IN] bandwidth    Sets the bandwidth
 *                          FSK : >= 2600 and <= 250000 Hz
 *                          LoRa: [0: 125 kHz, 1: 250 kHz,
 *                                 2: 500 kHz, 3: Reserved]
 * \param [IN] datarate     Sets the Datarate
 *                          FSK : 600..300000 bits/s
 *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
 *                                10: 1024, 11: 2048, 12: 4096  chips]
 * \param [IN] coderate     Sets the coding rate (LoRa only)
 *                          FSK : N/A ( set to 0 )
 *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
 * \param [IN] preambleLen  Sets the Preamble length
 *                          FSK : Number of bytes
 *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
 * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
 * \param [IN] payloadLen   Sets payload length when fixed length is used
 * \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]
 *
 * \retval airTime        Computed airTime (ms) for the given packet payload length
 */
// 计算给定的负载的空中数据包时间
uint32_t RadioTimeOnAir(lora_t *lora, RadioModems_t modem, uint32_t bandwidth,
                        uint32_t datarate, uint8_t coderate,
                        uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
                        bool crcOn);

/*!
 * \brief Sends the buffer of size. Prepares the packet to be sent and sets
 *        the radio in transmission
 *
 * \param [IN]: buffer     Buffer pointer
 * \param [IN]: size       Buffer size
 */
// 发送数据指定长度的数据
void RadioSend(lora_t *lora, uint8_t *buffer, uint8_t size);

/*!
 * \brief Sets the radio in sleep mode
 */
// 设置无线进入睡眠模式
void RadioSleep(lora_t *lora);

/*!
 * \brief Sets the radio in standby mode
 */
// 设置无线设备进入待机模式
void RadioStandby(lora_t *lora);

/*!
 * \brief Sets the radio in reception mode for the given time
 * \param [IN] timeout Reception timeout [ms]
 *                     [0: continuous, others timeout]
 */
// 设置无线接收 ，
void RadioRx(lora_t *lora, uint32_t timeout);

/*!
 * \brief Start a Channel Activity Detection
 */
// 启动通道活跃检查
void RadioStartCad(lora_t *lora);

/*!
 * \brief Sets the radio in continuous wave transmission mode
 *
 * \param [IN]: freq       Channel RF frequency
 * \param [IN]: power      Sets the output power [dBm]
 * \param [IN]: time       Transmission mode timeout [s]
 */
// 设置为连续发送模式
void RadioSetTxContinuousWave(lora_t *lora, uint32_t freq, int8_t power, uint16_t time);

/*!
 * \brief Reads the current RSSI value
 *
 * \retval rssiValue Current RSSI value in [dBm]
 */
// 读取当前 RSSI 的值
int16_t RadioRssi(lora_t *lora, RadioModems_t modem);

/*!
 * \brief Writes the radio register at the specified address
 *
 * \param [IN]: addr Register address
 * \param [IN]: data New register value
 */
// 将值写入寄存器
void RadioWrite(lora_t *lora, uint32_t addr, uint8_t data);

/*!
 * \brief Reads the radio register at the specified address
 *
 * \param [IN]: addr Register address
 * \retval data Register value
 */
// 读寄存器值
uint8_t RadioRead(lora_t *lora, uint32_t addr);

/*!
 * \brief Writes multiple radio registers starting at address
 *
 * \param [IN] addr   First Radio register address
 * \param [IN] buffer Buffer containing the new register's values
 * \param [IN] size   Number of registers to be written
 */
// 写数据到缓存区
void RadioWriteBuffer(lora_t *lora, uint32_t addr, uint8_t *buffer, uint8_t size);

/*!
 * \brief Reads multiple radio registers starting at address
 *
 * \param [IN] addr First Radio register address
 * \param [OUT] buffer Buffer where to copy the registers data
 * \param [IN] size Number of registers to be read
 */
// 读缓存区数据
void RadioReadBuffer(lora_t *lora, uint32_t addr, uint8_t *buffer, uint8_t size);

/*!
 * \brief Sets the maximum payload length.
 *
 * \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]
 * \param [IN] max        Maximum payload length in bytes
 */
// 设置最大载荷长度
void RadioSetMaxPayloadLength(lora_t *lora, RadioModems_t modem, uint8_t max);

/*!
 * \brief Sets the network to public or private. Updates the sync byte.
 *
 * \remark Applies to LoRa modem only
 *
 * \param [IN] enable if true, it enables a public network
 */
// 将网络设置为公开，或私有
void RadioSetPublicNetwork(lora_t *lora, bool enable);

/*!
 * \brief Gets the time required for the board plus radio to get out of sleep.[ms]
 *
 * \retval time Radio plus board wakeup time in ms.
 */
// 获取从睡眠到启动所需要的时间
uint32_t RadioGetWakeupTime(lora_t *lora);

/*!
 * \brief Process radio irq
 */
// 中断进程
void RadioIrqProcess(lora_t *lora);

/*!
 * \brief Sets the radio in reception mode with Max LNA gain for the given time
 * \param [IN] timeout Reception timeout [ms]
 *                     [0: continuous, others timeout]
 */
// 接受模式到最大增益时间
void RadioRxBoosted(lora_t *lora, uint32_t timeout);

/*!
 * \brief Sets the Rx duty cycle management parameters
 *
 * \param [in]  rxTime        Structure describing reception timeout value
 * \param [in]  sleepTime     Structure describing sleep timeout value
 */
// 设置接收占比时间
void RadioSetRxDutyCycle(lora_t *lora, uint32_t rxTime, uint32_t sleepTime);

/*
 * Local types definition
 */

/*!
 * FSK bandwidth definition
 */
typedef struct
{
    uint32_t bandwidth;
    uint8_t RegValue;
} FskBandwidth_t;

/*!
 * Precomputed FSK bandwidth registers values
 */
const FskBandwidth_t FskBandwidths[] =
    {
        {4800, 0x1F},
        {5800, 0x17},
        {7300, 0x0F},
        {9700, 0x1E},
        {11700, 0x16},
        {14600, 0x0E},
        {19500, 0x1D},
        {23400, 0x15},
        {29300, 0x0D},
        {39000, 0x1C},
        {46900, 0x14},
        {58600, 0x0C},
        {78200, 0x1B},
        {93800, 0x13},
        {117300, 0x0B},
        {156200, 0x1A},
        {187200, 0x12},
        {234300, 0x0A},
        {312000, 0x19},
        {373600, 0x11},
        {467000, 0x09},
        {500000, 0x00}, // Invalid Bandwidth
};

const RadioLoRaBandwidths_t Bandwidths[] = {LORA_BW_007,LORA_BW_010,LORA_BW_015,LORA_BW_020,
                                            LORA_BW_031,LORA_BW_041,LORA_BW_062,LORA_BW_125, 
																						LORA_BW_250, LORA_BW_500};
uint8_t MaxPayloadLength = 0xFF;

uint32_t TxTimeout = 0;
uint32_t RxTimeout = 0;

bool RxContinuous = true;

PacketStatus_t RadioPktStatus;
uint8_t RadioRxPayload[255];
/*
 * Private global variables
 */

/*!
 * Holds the current network type for the radio
 */
typedef struct
{
    bool Previous;
    bool Current;
} RadioPublicNetwork_t;

static RadioPublicNetwork_t RadioPublicNetwork = {false};

/*
 * Public global variables
 */

/*!
 * Radio hardware and global parameters
 */
SX126x_t SX126x;

/*!
 * \brief Holds the internal operating mode of the radio
 */
static RadioOperatingModes_t OperatingMode;

// 读取Busy 引脚电平
void SX126xWaitOnBusy(lora_t *lora)
{
    uint32_t u32_count = 0;
    while (lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_BUSY, 0, 0, 0) == 1)
    {
        if (u32_count++ > 1000)
        {
            u32_count = 0;
			
        }
        lora->gpio_and_delay_cb(lora, LoRa_MSG_DELAY_MILLI, 1, 0, 0);
    }
}

//------------------------ board code start �� board �ƶ������Ĵ��� -----------------
RadioOperatingModes_t SX126xGetOperatingMode(lora_t *lora)
{
    return OperatingMode;
}

void SX126xSetOperatingMode(lora_t *lora, RadioOperatingModes_t mode)
{
    OperatingMode = mode;
}

void SX126xIoTcxoInit(lora_t *lora)
{
    // No TCXO component available on this board design.
}

uint32_t SX126xGetBoardTcxoWakeupTime(lora_t *lora)
{
    return BOARD_TCXO_WAKEUP_TIME;
}

// 设置DIO2 为RF控制引脚
void SX126xIoRfSwitchInit(lora_t *lora)
{
    SX126xSetDio2AsRfSwitchCtrl(lora, true);
}

// 天线由内部控制，这里不做设置
void SX126xAntSwOn(lora_t *lora)
{
}
// 天线由内部控制，这里不做设置
void SX126xAntSwOff(lora_t *lora)
{
}

uint8_t SX126xGetDeviceId(lora_t *lora)
{
    return SX1262;
}

void SX126xSetRfTxPower(lora_t *lora, int8_t power)
{
    SX126xSetTxParams(lora, power, RADIO_RAMP_40_US);
}

void SX126xWriteRegister(lora_t *lora, uint16_t address, uint8_t value)
{
    SX126xWriteRegisters(lora, address, &value, 1);
}

uint8_t SX126xReadRegister(lora_t *lora, uint16_t address)
{
    uint8_t data;
    SX126xReadRegisters(lora, address, &data, 1);
    return data;
}

void SX126xWakeup(lora_t *lora)
{
    uint8_t command = 0;
    uint8_t status = 0;
    // CRITICAL_SECTION_BEGIN();

    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    command = RADIO_GET_STATUS;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);

    command = 0x00;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);

    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);

    // Wait for chip to be ready.
    SX126xWaitOnBusy(lora);

    // Update operating mode context variable
    SX126xSetOperatingMode(lora, MODE_STDBY_RC);

    // CRITICAL_SECTION_END();
}

/// @brief Sx126x 写命令
/// @param lora lora
/// @param command 指令
/// @param buffer  数据buffer
/// @param size    长度
void SX126xWriteCommand(lora_t *lora, RadioCommands_t command, uint8_t *buffer, uint16_t size)
{
    uint8_t status;
    SX126xCheckDeviceReady(lora);
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, size, buffer, &status);
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);
    if (command != RADIO_SET_SLEEP)
    {
        SX126xWaitOnBusy(lora);
    }
}

/// @brief Sx126x 命令读
/// @param lora lora 控制句柄
/// @param command
/// @param buffer
/// @param size
/// @return
uint8_t SX126xReadCommand(lora_t *lora, RadioCommands_t command, uint8_t *buffer, uint16_t size)
{
    uint8_t status = 0;
    SX126xCheckDeviceReady(lora);
    //SX126xCheckDeviceReady(lora);
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
	// 读状态
    uint8_t by = 0;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Receive, 1, &by, &status);
    lora->byte_cb(lora, LoRa_MSG_BYTE_Receive, size, buffer, &status);
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);
    SX126xWaitOnBusy(lora);
    return status;
}

/// @brief Sx126x 写寄存器
/// @param lora lora 控制结构体
/// @param address 寄存器地址
/// @param buffer 数据buf
/// @param size 数据长度
void SX126xWriteRegisters(lora_t *lora, uint16_t address, uint8_t *buffer, uint16_t size)
{
    uint8_t command = 0;
    uint8_t status = 0;
    SX126xCheckDeviceReady(lora);
    // 拉低CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    // 写寄存器命令
    command = RADIO_WRITE_REGISTER;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    // 发送寄存器地址
    command = (address & 0xFF00) >> 8;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    command = (address & 0x00FF) >> 8;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    // 写数据
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, size, buffer, &status);
    // 拉高CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);
    SX126xWaitOnBusy(lora);
}

/// @brief 读寄存器命令
/// @param lora lora 控制句柄
/// @param address 寄存器地址
/// @param buffer 数据buf
/// @param size 数据长度
void SX126xReadRegisters(lora_t *lora, uint16_t address, uint8_t *buffer, uint16_t size)
{
    uint8_t command = 0;
    uint8_t status = 0;
    SX126xCheckDeviceReady(lora);

    // 拉低CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    // 写寄存器命令
    command = RADIO_READ_REGISTER;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    // 发送寄存器地址
    command = (address & 0xFF00) >> 8;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    command = (address & 0x00FF) >> 8;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    // 读状态
    command = 0;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Receive, 1, &command, &status);
    // 读数据
    lora->byte_cb(lora, LoRa_MSG_BYTE_Receive, size, buffer, &status);
    // 拉高CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);

    SX126xWaitOnBusy(lora);
}

/// @brief Sx126x 写buffer
/// @param lora lora 控制句柄
/// @param offset 偏移地址
/// @param buffer 数据buf
/// @param size 数据长度
void SX126xWriteBuffer(lora_t *lora, uint8_t offset, uint8_t *buffer, uint8_t size)
{
    uint8_t status = 0;
    uint8_t command = 0;

    SX126xCheckDeviceReady(lora);

    // 拉低CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    // 发送命令
    command = RADIO_WRITE_BUFFER;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    // 发送偏移地址
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &offset, &status);
    // 发送数据
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, size, buffer, &status);
    // 拉高CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);

    SX126xWaitOnBusy(lora);
}

/// @brief SX126x 读buf
/// @param lora
/// @param offset
/// @param buffer
/// @param size
void SX126xReadBuffer(lora_t *lora, uint8_t offset, uint8_t *buffer, uint8_t size)
{
    uint8_t status = 0;
    uint8_t command = 0;
    SX126xCheckDeviceReady(lora);

    // 拉低CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 0, 0, 0);
    // 发送命令
    command = RADIO_READ_BUFFER;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &command, &status);
    // 发送偏移地址
    lora->byte_cb(lora, LoRa_MSG_BYTE_Transmit, 1, &offset, &status);
    // 读状态
    command = 0;
    lora->byte_cb(lora, LoRa_MSG_BYTE_Receive, size, &command, &status);
    // 读数据
    lora->byte_cb(lora, LoRa_MSG_BYTE_Receive, size, buffer, &status);
    // 拉高CS
    lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_CS, 1, 0, 0);
    SX126xWaitOnBusy(lora);
}
//------------------------ board code end -----------------

/*!
 * Returns the known FSK bandwidth registers value
 *
 * \param [IN] bandwidth Bandwidth value in Hz
 * \retval regValue Bandwidth register value.
 */

/// @brief 计算FSk 带宽 对应寄存器值
/// @param bandwidth 带宽
/// @return
static uint8_t RadioGetFskBandwidthRegValue(uint32_t bandwidth)
{
    uint8_t i;

    if (bandwidth == 0)
    {
        return (0x1F);
    }

    for (i = 0; i < (sizeof(FskBandwidths) / sizeof(FskBandwidth_t)) - 1; i++)
    {
        if ((bandwidth >= FskBandwidths[i].bandwidth) && (bandwidth < FskBandwidths[i + 1].bandwidth))
        {
            return FskBandwidths[i + 1].RegValue;
        }
    }
    // ERROR: Value not found
    while (1)
        ;
}

/// @brief 无线初始化
/// @param lora
void RadioInit(lora_t *lora)
{
    SX126xInit(lora); //
    SX126xSetStandby(lora, STDBY_RC);
    SX126xSetRegulatorMode(lora, USE_DCDC);

    SX126xSetBufferBaseAddress(lora, 0x00, 0x00);
    SX126xSetTxParams(lora, 0, RADIO_RAMP_200_US);
    SX126xSetDioIrqParams(lora, IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE);
	
	  //RadioAddRegisterToRetentionList(lora, REG_RX_GAIN );
    //RadioAddRegisterToRetentionList( lora,REG_TX_MODULATION );

    // SX126xTimerInit();
}

/// @brief 获取当前状态
/// @param lora  lora 控制句柄
/// @return  Radio status :RF_IDLE, RF_RX_RUNNING, RF_TX_RYNNING
RadioState_t RadioGetStatus(lora_t *lora)
{
    switch (SX126xGetOperatingMode(lora))
    {
    case MODE_TX:
        return RF_TX_RUNNING;
    case MODE_RX:
        return RF_RX_RUNNING;
    case MODE_CAD:
        return RF_CAD;
    default:
        return RF_IDLE;
    }
}

/// @brief 设置调制模式
/// @param lora lora 控制句柄
/// @param modem 模式 // 0：FSk 1：Lora
void RadioSetModem(lora_t *lora, RadioModems_t modem)
{
    switch (modem)
    {
    default:
    case MODEM_FSK:
        SX126xSetPacketType(lora, PACKET_TYPE_GFSK);
        // When switching to GFSK mode the LoRa SyncWord register value is reset
        // Thus, we also reset the RadioPublicNetwork variable
        RadioPublicNetwork.Current = false;
        break;
    case MODEM_LORA:
        SX126xSetPacketType(lora, PACKET_TYPE_LORA);
        // Public/Private network register is reset when switching modems
        if (RadioPublicNetwork.Current != RadioPublicNetwork.Previous)
        {
            RadioPublicNetwork.Current = RadioPublicNetwork.Previous;
            RadioSetPublicNetwork(lora, RadioPublicNetwork.Current);
        }
        break;
    }
}

/// @brief 设置通道频率
/// @param lora lora 控制句柄
/// @param freq 无线频率
void RadioSetChannel(lora_t *lora, uint32_t freq)
{
    SX126xSetRfFrequency(lora, freq);
}

/// @brief
/// @param lora
/// @param freq
/// @param rxBandwidth
/// @param rssiThresh
/// @param maxCarrierSenseTime
/// @return
bool RadioIsChannelFree(lora_t *lora, uint32_t freq, uint32_t rxBandwidth, int16_t rssiThresh, uint32_t maxCarrierSenseTime)
{
    bool status = true;
    int16_t rssi = 0;
    uint32_t count = 0;

    RadioSetModem(lora, MODEM_FSK);

    RadioSetChannel(lora, freq);

    // Set Rx bandwidth. Other parameters are not used.
    RadioSetRxConfig(lora, MODEM_FSK, rxBandwidth, 600, 0, rxBandwidth, 3, 0, false,
                     0, false, 0, 0, false, true);
    RadioRx(lora, 0);
    lora->gpio_and_delay_cb(lora, LoRa_MSG_DELAY_MILLI, 1, 0, 0);

    // Perform carrier sense for maxCarrierSenseTime
    count = 0;
    while (count < maxCarrierSenseTime)
    {
        rssi = RadioRssi(lora, MODEM_FSK);

        if (rssi > rssiThresh)
        {
            status = false;
            break;
        }
        lora->gpio_and_delay_cb(lora, LoRa_MSG_DELAY_MILLI, 1, 0, 0);
        count++;
    }
    RadioSleep(lora);
    return status;
}

uint32_t RadioRandom(lora_t *lora)
{
    uint32_t rnd = 0;

    /*
     * Radio setup for random number generation
     */
    // Set LoRa modem ON
    RadioSetModem(lora, MODEM_LORA);

    // Disable LoRa modem interrupts
    SX126xSetDioIrqParams(lora, IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE);

    rnd = SX126xGetRandom(lora);

    return rnd;
}

void RadioSetRxConfig(lora_t *lora, RadioModems_t modem, uint32_t bandwidth,
                      uint32_t datarate, uint8_t coderate,
                      uint32_t bandwidthAfc, uint16_t preambleLen,
                      uint16_t symbTimeout, bool fixLen,
                      uint8_t payloadLen,
                      bool crcOn, bool freqHopOn, uint8_t hopPeriod,
                      bool iqInverted, bool rxContinuous)
{
    uint8_t syncWordBuf[] = {0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00};

    RxContinuous = rxContinuous;
    if (rxContinuous == true)
    {
        symbTimeout = 0;
    }
    if (fixLen == true)
    {
        MaxPayloadLength = payloadLen;
    }
    else
    {
        MaxPayloadLength = 0xFF;
    }

    switch (modem)
    {
    case MODEM_FSK:
        SX126xSetStopRxTimerOnPreambleDetect(lora, false);
        SX126x.ModulationParams.PacketType = PACKET_TYPE_GFSK;

        SX126x.ModulationParams.Params.Gfsk.BitRate = datarate;
        SX126x.ModulationParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
        SX126x.ModulationParams.Params.Gfsk.Bandwidth = RadioGetFskBandwidthRegValue(bandwidth << 1); // SX126x badwidth is double sided

        SX126x.PacketParams.PacketType = PACKET_TYPE_GFSK;
        SX126x.PacketParams.Params.Gfsk.PreambleLength = (preambleLen << 3); // convert byte into bit
        SX126x.PacketParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_08_BITS;
        SX126x.PacketParams.Params.Gfsk.SyncWordLength = 3 << 3; // convert byte into bit
        SX126x.PacketParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
        SX126x.PacketParams.Params.Gfsk.HeaderType = (fixLen == true) ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;
        SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength;
        if (crcOn == true)
        {
            SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_2_BYTES_CCIT;
        }
        else
        {
            SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
        }
        SX126x.PacketParams.Params.Gfsk.DcFree = RADIO_DC_FREEWHITENING;

        RadioStandby(lora);
        RadioSetModem(lora, (SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK) ? MODEM_FSK : MODEM_LORA);
        SX126xSetModulationParams(lora, &SX126x.ModulationParams);
        SX126xSetPacketParams(lora, &SX126x.PacketParams);
        SX126xSetSyncWord(lora, syncWordBuf);
        SX126xSetWhiteningSeed(lora, 0x01FF);

        RxTimeout = (uint32_t)symbTimeout * 8000UL / datarate;
        break;

    case MODEM_LORA:
        SX126xSetStopRxTimerOnPreambleDetect(lora, false);
        SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
        SX126x.ModulationParams.Params.LoRa.SpreadingFactor = (RadioLoRaSpreadingFactors_t)datarate;
        SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
        SX126x.ModulationParams.Params.LoRa.CodingRate = (RadioLoRaCodingRates_t)coderate;

        if (((bandwidth == 0) && ((datarate == 11) || (datarate == 12))) ||
            ((bandwidth == 1) && (datarate == 12)))
        {
            SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01;
        }
        else
        {
            SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00;
        }

        SX126x.PacketParams.PacketType = PACKET_TYPE_LORA;

        if ((SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5) ||
            (SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6))
        {
            if (preambleLen < 12)
            {
                SX126x.PacketParams.Params.LoRa.PreambleLength = 12;
            }
            else
            {
                SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
            }
        }
        else
        {
            SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
        }

        SX126x.PacketParams.Params.LoRa.HeaderType = (RadioLoRaPacketLengthsMode_t)fixLen;

        SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength;
        SX126x.PacketParams.Params.LoRa.CrcMode = (RadioLoRaCrcModes_t)crcOn;
        SX126x.PacketParams.Params.LoRa.InvertIQ = (RadioLoRaIQModes_t)iqInverted;

        RadioStandby(lora);
        RadioSetModem(lora, (SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK) ? MODEM_FSK : MODEM_LORA);
        SX126xSetModulationParams(lora, &SX126x.ModulationParams);
        SX126xSetPacketParams(lora, &SX126x.PacketParams);
        SX126xSetLoRaSymbNumTimeout(lora, symbTimeout);

        // WORKAROUND - Optimizing the Inverted IQ Operation, see DS_SX1261-2_V1.2 datasheet chapter 15.4
        if (SX126x.PacketParams.Params.LoRa.InvertIQ == LORA_IQ_INVERTED)
        {
            // RegIqPolaritySetup = @address 0x0736
            SX126xWriteRegister(lora, 0x0736, SX126xReadRegister(lora, 0x0736) & ~(1 << 2));
        }
        else
        {
            // RegIqPolaritySetup @address 0x0736
            SX126xWriteRegister(lora, 0x0736, SX126xReadRegister(lora, 0x0736) | (1 << 2));
        }
        // WORKAROUND END

        // Timeout Max, Timeout handled directly in SetRx function
        RxTimeout = 0xFFFF;

        break;
    }
}

/// @brief 设置无线发送参数
/// @param lora lora 设备句柄
/// @param modem 无线模式 0：FSK 1：LoRa
/// @param power 发射功能
/// @param fdev  设置频率偏差 （仅FSK模式）
/// @param bandwidth 设置带宽 （仅LoRa模式）0：125Khz，1：250KHz，2：500Khz 3：Reserved
/// @param datarate  设置速度速率 FSK：600~300000bit/s LoRa：6：64 7：128，8：256 9：512 10：1024 11：2048 12 4096
/// @param coderate  设置编码率 （仅LoRa模式） 1：4/5 2：4/6 3：4/7 4：4/8
/// @param preambleLen 前导码长度
/// @param fixLen 定包长度[0:变长]
/// @param crcOn 使能/失能CRC校验 [0:OFF,1:ON]
/// @param freqHopOn 使能/失能 调频功能 （仅LoRa）Lora: 0:OFF 1:ON
/// @param hopPeriod
/// @param iqInverted
void RadioSetTxConfig(lora_t *lora, RadioModems_t modem, int8_t power, uint32_t fdev,
                      uint32_t bandwidth, uint32_t datarate,
                      uint8_t coderate, uint16_t preambleLen,
                      bool fixLen, bool crcOn, bool freqHopOn,
                      uint8_t hopPeriod, bool iqInverted)
{
    uint8_t syncWordBuf[] = {0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00};

    switch (modem)
    {
    case MODEM_FSK:
        SX126x.ModulationParams.PacketType = PACKET_TYPE_GFSK;
        SX126x.ModulationParams.Params.Gfsk.BitRate = datarate;

        SX126x.ModulationParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
        SX126x.ModulationParams.Params.Gfsk.Bandwidth = RadioGetFskBandwidthRegValue(bandwidth << 1); // SX126x badwidth is double sided
        SX126x.ModulationParams.Params.Gfsk.Fdev = fdev;

        SX126x.PacketParams.PacketType = PACKET_TYPE_GFSK;
        SX126x.PacketParams.Params.Gfsk.PreambleLength = (preambleLen << 3); // convert byte into bit
        SX126x.PacketParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_08_BITS;
        SX126x.PacketParams.Params.Gfsk.SyncWordLength = 3 << 3; // convert byte into bit
        SX126x.PacketParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
        SX126x.PacketParams.Params.Gfsk.HeaderType = (fixLen == true) ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;

        if (crcOn == true)
        {
            SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_2_BYTES_CCIT;
        }
        else
        {
            SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
        }
        SX126x.PacketParams.Params.Gfsk.DcFree = RADIO_DC_FREEWHITENING;

        RadioStandby(lora);
        RadioSetModem(lora, (SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK) ? MODEM_FSK : MODEM_LORA);
        SX126xSetModulationParams(lora, &SX126x.ModulationParams);
        SX126xSetPacketParams(lora, &SX126x.PacketParams);
        SX126xSetSyncWord(lora, syncWordBuf);
        SX126xSetWhiteningSeed(lora, 0x01FF);
        break;

    case MODEM_LORA:
        SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
        SX126x.ModulationParams.Params.LoRa.SpreadingFactor = (RadioLoRaSpreadingFactors_t)datarate;
        SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
        SX126x.ModulationParams.Params.LoRa.CodingRate = (RadioLoRaCodingRates_t)coderate;

        if (((bandwidth == 0) && ((datarate == 11) || (datarate == 12))) ||
            ((bandwidth == 1) && (datarate == 12)))
        {
            SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01;
        }
        else
        {
            SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00;
        }

        SX126x.PacketParams.PacketType = PACKET_TYPE_LORA;

        if ((SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5) ||
            (SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6))
        {
            if (preambleLen < 12)
            {
                SX126x.PacketParams.Params.LoRa.PreambleLength = 12;
            }
            else
            {
                SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
            }
        }
        else
        {
            SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
        }

        SX126x.PacketParams.Params.LoRa.HeaderType = (RadioLoRaPacketLengthsMode_t)fixLen;
        SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength;
        SX126x.PacketParams.Params.LoRa.CrcMode = (RadioLoRaCrcModes_t)crcOn;
        SX126x.PacketParams.Params.LoRa.InvertIQ = (RadioLoRaIQModes_t)iqInverted;

        RadioStandby(lora);
        RadioSetModem(lora, (SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK) ? MODEM_FSK : MODEM_LORA);
        SX126xSetModulationParams(lora, &SX126x.ModulationParams);
        SX126xSetPacketParams(lora, &SX126x.PacketParams);
        break;
    }

    // WORKAROUND - Modulation Quality with 500 kHz LoRa Bandwidth, see DS_SX1261-2_V1.2 datasheet chapter 15.1
    if ((modem == MODEM_LORA) && (SX126x.ModulationParams.Params.LoRa.Bandwidth == LORA_BW_500))
    {
        // RegTxModulation = @address 0x0889
        SX126xWriteRegister(lora, 0x0889, SX126xReadRegister(lora, 0x0889) & ~(1 << 2));
    }
    else
    {
        // RegTxModulation = @address 0x0889
        SX126xWriteRegister(lora, 0x0889, SX126xReadRegister(lora, 0x0889) | (1 << 2));
    }
    // WORKAROUND END

    SX126xSetRfTxPower(lora, power);
}

bool RadioCheckRfFrequency(lora_t *lora, uint32_t frequency)
{
    return true;
}

static uint32_t RadioGetLoRaBandwidthInHz(RadioLoRaBandwidths_t bw)
{
    uint32_t bandwidthInHz = 0;

    switch (bw)
    {
    case LORA_BW_007:
        bandwidthInHz = 7812UL;
        break;
    case LORA_BW_010:
        bandwidthInHz = 10417UL;
        break;
    case LORA_BW_015:
        bandwidthInHz = 15625UL;
        break;
    case LORA_BW_020:
        bandwidthInHz = 20833UL;
        break;
    case LORA_BW_031:
        bandwidthInHz = 31250UL;
        break;
    case LORA_BW_041:
        bandwidthInHz = 41667UL;
        break;
    case LORA_BW_062:
        bandwidthInHz = 62500UL;
        break;
    case LORA_BW_125:
        bandwidthInHz = 125000UL;
        break;
    case LORA_BW_250:
        bandwidthInHz = 250000UL;
        break;
    case LORA_BW_500:
        bandwidthInHz = 500000UL;
        break;
    }

    return bandwidthInHz;
}

static uint32_t RadioGetGfskTimeOnAirNumerator(uint32_t datarate, uint8_t coderate,
                                               uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
                                               bool crcOn)
{
    const RadioAddressComp_t addrComp = RADIO_ADDRESSCOMP_FILT_OFF;
    const uint8_t syncWordLength = 3;

    return (preambleLen << 3) +
           ((fixLen == false) ? 8 : 0) +
           (syncWordLength << 3) +
           ((payloadLen +
             (addrComp == RADIO_ADDRESSCOMP_FILT_OFF ? 0 : 1) +
             ((crcOn == true) ? 2 : 0))
            << 3);
}

static uint32_t RadioGetLoRaTimeOnAirNumerator(uint32_t bandwidth,
                                               uint32_t datarate, uint8_t coderate,
                                               uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
                                               bool crcOn)
{
    int32_t crDenom = coderate + 4;
    bool lowDatareOptimize = false;
    int32_t ceilDenominator;
    int32_t ceilNumerator = 0;
    int32_t intermediate = 0;

    // Ensure that the preamble length is at least 12 symbols when using SF5 or
    // SF6
    if ((datarate == 5) || (datarate == 6))
    {
        if (preambleLen < 12)
        {
            preambleLen = 12;
        }
    }

    if (((bandwidth == 0) && ((datarate == 11) || (datarate == 12))) ||
        ((bandwidth == 1) && (datarate == 12)))
    {
        lowDatareOptimize = true;
    }

    ceilNumerator = (payloadLen << 3) +
                    (crcOn ? 16 : 0) -
                    (4 * datarate) +
                    (fixLen ? 0 : 20);

    if (datarate <= 6)
    {
        ceilDenominator = 4 * datarate;
    }
    else
    {
        ceilNumerator += 8;

        if (lowDatareOptimize == true)
        {
            ceilDenominator = 4 * (datarate - 2);
        }
        else
        {
            ceilDenominator = 4 * datarate;
        }
    }

    if (ceilNumerator < 0)
    {
        ceilNumerator = 0;
    }

    // Perform integral ceil()
    intermediate =
        ((ceilNumerator + ceilDenominator - 1) / ceilDenominator) * crDenom + preambleLen + 12;

    if (datarate <= 6)
    {
        intermediate += 2;
    }

    return (uint32_t)((4 * intermediate + 1) * (1 << (datarate - 2)));
}

uint32_t RadioTimeOnAir(lora_t *lora, RadioModems_t modem, uint32_t bandwidth,
                        uint32_t datarate, uint8_t coderate,
                        uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
                        bool crcOn)
{
    uint32_t numerator = 0;
    uint32_t denominator = 1;

    switch (modem)
    {
    case MODEM_FSK:
    {
        numerator = 1000U * RadioGetGfskTimeOnAirNumerator(datarate, coderate,
                                                           preambleLen, fixLen,
                                                           payloadLen, crcOn);
        denominator = datarate;
    }
    break;
    case MODEM_LORA:
    {
        numerator = 1000U * RadioGetLoRaTimeOnAirNumerator(bandwidth, datarate,
                                                           coderate, preambleLen,
                                                           fixLen, payloadLen, crcOn);
        denominator = RadioGetLoRaBandwidthInHz(Bandwidths[bandwidth]);
    }
    break;
    }
    // Perform integral ceil()
    return (numerator + denominator - 1) / denominator;
}

void RadioSend(lora_t *lora, uint8_t *buffer, uint8_t size)
{
    SX126xSetDioIrqParams(lora, IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_NONE,
                          IRQ_RADIO_NONE);

    if (SX126xGetPacketType(lora) == PACKET_TYPE_LORA)
    {
        SX126x.PacketParams.Params.LoRa.PayloadLength = size;
    }
    else
    {
        SX126x.PacketParams.Params.Gfsk.PayloadLength = size;
    }
    SX126xSetPacketParams(lora, &SX126x.PacketParams);

    SX126xSendPayload(lora, buffer, size, 0);
    // SX126xSetTxTimerValue(lora,TxTimeout);
    // SX126xTxTimerStart(lora);
}

void RadioSleep(lora_t *lora)
{
    SleepParams_t params = {0};

    params.Fields.WarmStart = 1;
    SX126xSetSleep(lora, params);
    lora->gpio_and_delay_cb(lora, LoRa_MSG_DELAY_MILLI, 2, 0, 0);
}

void RadioStandby(lora_t *lora)
{
    SX126xSetStandby(lora, STDBY_RC);
}

void RadioRx(lora_t *lora, uint32_t timeout)
{
    SX126xSetDioIrqParams(lora, IRQ_RADIO_ALL, // IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_ALL,       // IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_NONE,
                          IRQ_RADIO_NONE);

    if (timeout != 0)
    {
        // SX126xSetRxTimerValue(timeout);
        // SX126xRxTimerStart();
    }

    if (RxContinuous == true)
    {
        SX126xSetRx(lora, 0xFFFFFF); // Rx Continuous
    }
    else
    {
        SX126xSetRx(lora, RxTimeout << 6);
    }
}

void RadioRxBoosted(lora_t *lora, uint32_t timeout)
{
    SX126xSetDioIrqParams(lora, IRQ_RADIO_ALL, // IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_ALL,       // IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_NONE,
                          IRQ_RADIO_NONE);

    if (timeout != 0)
    {
        // SX126xSetRxTimerValue(timeout);
        // SX126xRxTimerStart();
    }

    if (RxContinuous == true)
    {
        SX126xSetRxBoosted(lora, 0xFFFFFF); // Rx Continuous
    }
    else
    {
        SX126xSetRxBoosted(lora, RxTimeout << 6);
    }
}

void RadioSetRxDutyCycle(lora_t *lora, uint32_t rxTime, uint32_t sleepTime)
{
    SX126xSetRxDutyCycle(lora, rxTime, sleepTime);
}

void RadioStartCad(lora_t *lora)
{
    SX126xSetDioIrqParams(lora, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_RADIO_NONE, IRQ_RADIO_NONE);
    SX126xSetCad(lora);
}

void RadioSetTxContinuousWave(lora_t *lora, uint32_t freq, int8_t power, uint16_t time)
{

    SX126xSetRfFrequency(lora, freq);
    SX126xSetRfTxPower(lora, power);
    SX126xSetTxContinuousWave(lora);

    // SX126xSetTxTimerValue(timeout);
    // SX126xTxTimerStart();
}

int16_t RadioRssi(lora_t *lora, RadioModems_t modem)
{
    return SX126xGetRssiInst(lora);
}

void RadioWrite(lora_t *lora, uint32_t addr, uint8_t data)
{
    SX126xWriteRegister(lora, addr, data);
}

uint8_t RadioRead(lora_t *lora, uint32_t addr)
{
    return SX126xReadRegister(lora, addr);
}

void RadioWriteBuffer(lora_t *lora, uint32_t addr, uint8_t *buffer, uint8_t size)
{
    SX126xWriteRegisters(lora, addr, buffer, size);
}

void RadioReadBuffer(lora_t *lora, uint32_t addr, uint8_t *buffer, uint8_t size)
{
    SX126xReadRegisters(lora, addr, buffer, size);
}

void RadioSetMaxPayloadLength(lora_t *lora, RadioModems_t modem, uint8_t max)
{
    if (modem == MODEM_LORA)
    {
        SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength = max;
        SX126xSetPacketParams(lora, &SX126x.PacketParams);
    }
    else
    {
        if (SX126x.PacketParams.Params.Gfsk.HeaderType == RADIO_PACKET_VARIABLE_LENGTH)
        {
            SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength = max;
            SX126xSetPacketParams(lora, &SX126x.PacketParams);
        }
    }
}

void RadioSetPublicNetwork(lora_t *lora, bool enable)
{
    RadioPublicNetwork.Current = RadioPublicNetwork.Previous = enable;

    RadioSetModem(lora, MODEM_LORA);
    if (enable == true)
    {
        // Change LoRa modem SyncWord
        SX126xWriteRegister(lora, REG_LR_SYNCWORD, (LORA_MAC_PUBLIC_SYNCWORD >> 8) & 0xFF);
        SX126xWriteRegister(lora, REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF);
    }
    else
    {
        // Change LoRa modem SyncWord
        SX126xWriteRegister(lora, REG_LR_SYNCWORD, (LORA_MAC_PRIVATE_SYNCWORD >> 8) & 0xFF);
        SX126xWriteRegister(lora, REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF);
    }
}

uint32_t RadioGetWakeupTime(lora_t *lora)
{
    return SX126xGetBoardTcxoWakeupTime(lora) + RADIO_WAKEUP_TIME;
}

/// @brief sx126x 接收数据
/// @param lora lora 控制句柄
/// @param buf 数据buf
/// @param len 数据长度
/// @return 
uint8_t sx126xRxData(lora_t *lora, uint8_t *buf, uint8_t *len)
{
    uint16_t irqRegs = 0;
	  irqRegs = SX126xGetIrqStatus(lora);
    if (1 == lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_ReadDio1, 0, 0, 0))
    {
        irqRegs = SX126xGetIrqStatus(lora);
        SX126xClearIrqStatus(lora, irqRegs);
			 if ((irqRegs & IRQ_RX_TX_TIMEOUT) == IRQ_RX_TX_TIMEOUT)
			 {
				 return 3;
			 }
        if ((irqRegs & IRQ_RX_DONE) == IRQ_RX_DONE)
        {
            if ((irqRegs & IRQ_CRC_ERROR) == IRQ_CRC_ERROR)
            {
                return 2; // CRC 错误
            }
            else
            {
                SX126xGetPayload(lora, buf, len, 255);
                SX126xGetPacketStatus(lora, &RadioPktStatus);
                return 0;
            }
        }
    }
    return 1;
}

/// @brief Sx126x 初始化
/// @param lora 
/// @param byte_cb 
/// @param gpio_and_delay 
void Lora_Setup_SX126x_noname_f(lora_t *lora, lora_msg_cb byte_cb, lora_msg_cb gpio_and_delay)
{
    lora->byte_cb = byte_cb;
    lora->gpio_and_delay_cb = gpio_and_delay;

    RadioInit(lora);
}

/// @brief sx126x 初始化
/// @param lora lora 控制句柄
/// @param stting lora 配置参数
void sx126xLoraInit(lora_t *lora, lora_config_t *stting)
{
    RadioSetChannel(lora, stting->RFFrequency); // 频率
    RadioSetTxConfig(lora, MODEM_LORA, stting->Power, 0,
                     stting->SignalBw, stting->SpreadingFactor,
                     stting->ErrorCoding, 8, 0, true, 0, 0, 0);

    RadioSetRxConfig(lora, MODEM_LORA, stting->SignalBw,
                     stting->SpreadingFactor, stting->ErrorCoding, 0, 8, 0, false, 0, true, 0, 0, 0, 0);
}

/// @brief lora 发送数据
/// @param lora lora 控制句柄
/// @param fr 发送频率
/// @param buffer 数据buf
/// @param size 长度
/// @param time_out 超时时间
/// @return 
uint8_t sx126xSend(lora_t *lora, uint32_t fr, uint8_t *buffer, uint8_t size, uint32_t time_out)
{
    uint16_t irqRegs = 0;
    SX126xSetDioIrqParams(lora, IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_NONE,
                          IRQ_RADIO_NONE);
    if (SX126xGetPacketType(lora) == PACKET_TYPE_LORA)
    {
        SX126x.PacketParams.Params.LoRa.PayloadLength = size;
    }
    else
    {
        SX126x.PacketParams.Params.Gfsk.PayloadLength = size;
    }
    SX126xSetPacketParams(lora, &SX126x.PacketParams); //

    SX126xSendPayload(lora, buffer, size, 0);
    if (lora->gpio_and_delay_cb(lora, LoRa_MSG_GPIO_EXIT_DIO1,0, &time_out, 0) == 0)
    {        irqRegs = SX126xGetIrqStatus(lora);
        SX126xClearIrqStatus(lora, irqRegs);
        if ((irqRegs & IRQ_TX_DONE) == IRQ_TX_DONE)
        {
					  //RadioStandby(lora);
            return 0;
        }
    }
		//RadioStandby(lora);
    return 1;
}
/// @brief 启动接收
/// @param lora lora 控制句柄
/// @param fr 接收频率
void sx126xStartRx(lora_t *lora, uint32_t fr)
{
	  RxContinuous=true;
    SX126xSetDioIrqParams(lora,   IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
                          IRQ_RADIO_NONE,
                          IRQ_RADIO_NONE);
    if (RxContinuous == true)
    {
        SX126xSetRx(lora, 0xFFFFFF); // Rx Continuous
    }
    else
    {
			  RxTimeout=0;
        SX126xSetRx(lora, RxTimeout << 6);
    }
}
